﻿using System;
using System.Web;
using System.Collections;
using System.Text;

namespace TWS.Controller.Paging
{
    /// <summary>
    /// Lớp phân trang.
    /// </summary>
    public class Paging
    {
        private int totalCount = 0;    // tổng số record trả về từ CSDL.
        private int maxPage = 0;    // số trang lớn nhất.
        private int lowerBoundary;       // vùng số thấp.
        private int upperBoundary;       // vùng số cao.
        private string url;                 // lấy địa chỉ url của trang; 

        public Paging(int totalCount)
        {
            this.id = "paging"; // chưa dùng.
            this.queryString = "";
            this.param = "page";

            this.perPage = 10;
            this.currentPage = 1;

            this.linksBefore = 2;
            this.linksAfter = 2;

            this.firstText = " trang đầu";
            this.lastText = " trang cuối";
            this.NextText = " tiếp";
            this.PrevText = " trước";

            this.showFirst = false;
            this.showPrev = false;
            this.showNext = false;
            this.showLast = false;
            this.showMore = true;
            this.showPageNumber = true;

            this.currentMode = Mode.None; // tùy chọn: [none | combobox | editbox].
            this.inputInValid = "Số trang không tồn tại.";
            this.targetString = string.Empty;

            this.totalCount = totalCount;

            this.MaxPage();

            if (this.maxPage > linksAfter)
                this.ShowLast = true;

        }

        /// <summary>
        /// Hàm tính số trang lớn nhất, tính tròn tăng từ totalCount.
        /// </summary>
        private void MaxPage()
        {
            if (this.totalCount != 0)
            {
                this.maxPage = this.totalCount / this.PerPage;

                if ((this.maxPage * this.perPage) < totalCount)
                {
                    this.maxPage += 1;
                }
            }
        }

        /// <summary>
        /// Hàm lấy địa chỉ url của trang đặt paging.
        /// </summary>
        /// <param name="pageNumber">số trang sẽ xem.</param>
        /// <returns>string</returns>
        private string TargetUrl(double pageNumber)
        {
            string url = "";
            int find = this.QueryString.IndexOf("?");

            if (find > 0)
            {
                url = this.QueryString + "&" + this.Param + "=" + pageNumber.ToString();
            }
            else
            {
                url = this.QueryString + "?" + this.Param + "=" + pageNumber.ToString();
            }

            return url;
        }

        /// <summary>
        /// Hàm xây dựng phân trang
        /// </summary>
        /// <returns>trả về chuỗi html với cấu trúc phân trang.</returns>
        public string BuildPaging()
        {
            StringBuilder outputPage = new StringBuilder();

            this.MaxPage();

            if (this.totalCount > this.PerPage)
            {
                /**
                 * thêm hàm javascript xử lý khi CurrentMode là Combobox hay Editbox.
                 */
                if (this.showPageNumber)
                {
                    if (this.CurrentMode == Mode.Editbox)
                    {
                        outputPage.Append("<script type=\"text/javascript\">");
                        outputPage.AppendLine();
                        outputPage.Append("window.addEvent('domready', function() {");
                        outputPage.AppendLine();
                        outputPage.Append("\tpagingEditbox(\"" + this.QueryString + "\", " + this.maxPage + ", \"" + this.Param + "\", \"" + this.InputInValid + "\");");
                        outputPage.AppendLine();
                        outputPage.Append("});</script>");
                        outputPage.AppendLine();
                    }
                    if (this.CurrentMode == Mode.Combobox)
                    {
                        outputPage.Append("<script type=\"text/javascript\">");
                        outputPage.AppendLine();
                        outputPage.Append("window.addEvent('domready', function() {");
                        outputPage.AppendLine();
                        outputPage.Append("\tpagingCombobox(\"" + this.QueryString + "\", \"" + this.Param + "\")");
                        outputPage.AppendLine();
                        outputPage.Append("});</script>");
                        outputPage.AppendLine();
                    }
                }

                /**
                 * xét giá trị lại biến "currentPage" trang hiện tại đang xem.
                 */
                //if (HttpContext.Current.Request.QueryString[this.Param] != null)
                //{
                //    this.currentPage = ConvertUtils.ToInt(HttpContext.Current.Request.QueryString[this.Param]);
                //}

                /**
    		     * tính vùng số (thấp) thoát ra khỏi liên kết trước trang hiện tại.
    		     * vd: 1 2 [3].
    		     */
                if ((this.CurrentPage - this.LinksBefore) < 1)
                {
                    this.lowerBoundary = 1;
                }
                else
                {
                    this.lowerBoundary = this.CurrentPage - this.LinksBefore;
                }

                /**
    		     * tính vùng số (cao) thoát ra khỏi liên kết sau trang hiện tại.
    		     * vd: [3] 4 5.
    		     */
                if ((this.CurrentPage + this.LinksAfter) > this.maxPage)
                {
                    this.upperBoundary = this.maxPage;
                }
                else
                {
                    this.upperBoundary = this.CurrentPage + this.LinksAfter;
                }

                /**
			     * tạo link từ miền giá trị lấy được trong khoảng giới hạn.
			     * khởi tạo mảng và truyền giá trị tương ứng vào mảng đó.
			     * vd: ... 1 2 [3] 4 5 ...
			     */
                ArrayList pageLinks = new ArrayList();

                if (this.ShowMore && (this.CurrentPage - this.LinksBefore) > 1)
                {
                    pageLinks.Add("<span> ...</span>");
                }

                for (double i = this.lowerBoundary; i <= this.upperBoundary; i++)
                {
                    if (this.CurrentPage == i)
                    {
                        switch (this.CurrentMode)
                        {
                            case Mode.None: 
                                pageLinks.Add("<li class=\"current\"><a href=\"#\">" + i + "</a></li>");
                                break;
                            case Mode.Combobox: 
                                StringBuilder combobox = new StringBuilder();
                                combobox.Append("<select id=\"paging-mode-combobox\" class=\"current-combobox\">");
                                for (double j = 1; j <= this.maxPage; j++)
                                {
                                    combobox.Append("<option value=\"" + j + "\"");
                                    if (this.CurrentPage == j)
                                    {
                                        combobox.Append(" selected=\"selected\"");
                                    }
                                    combobox.Append(">" + j + "</option>");
                                    combobox.AppendLine();
                                }
                                combobox.Append("</select>");
                                combobox.AppendLine();
                                pageLinks.Add(combobox.ToString());
                                break;
                            case Mode.Editbox: 
                                string editbox = "<input type=\"text\" id=\"paging-mode-editbox\" class=\"current-editbox\" value=\"" + i + "\">";
                                pageLinks.Add(editbox);
                                break;
                            default:
                                pageLinks.Add("<li class=\"current\"><a href=\"#\">" + i + "</a></li>");
                                break;
                        }                                                
                    }
                    else 
                    {

                        pageLinks.Add("<li><a href=\"" + this.TargetUrl(i) + "\" " + this.targetString + ">" + i + "</a></li>");

                    }
                }

                if (this.ShowMore && (this.CurrentPage + this.LinksAfter) < this.maxPage)
                {
                    pageLinks.Add("<span> ...</span>");
                }

                /**
    	         * tạo link: first | prev | next | last.
    	         */
                string firstLink = null;
                string prevLink = null;
                string nextLink = null;
                string lastLink = null;

                if (this.CurrentPage != 1)
                {
                    firstLink = "<li><a title=\"Trang Đầu\" style=\"font-size:8pt;\" href=\"" + this.TargetUrl(1) + "\" >" + this.FirstText + "</a></li>";
                    prevLink = "<li><a title=\"Trang Trước\" href=\"" + this.TargetUrl(this.CurrentPage - 1) + "\">" + this.prevText + "</a></li>";
                }
                if (this.CurrentPage != this.maxPage)
                {
                    nextLink = "<li><a title=\"Trang Kế\" href=\"" + this.TargetUrl(this.CurrentPage + 1) + "\">" + this.nextText + "</a></li>";
                    lastLink = "<li><a title=\"Trang Cuối\" style=\"font-size:8pt;\" href=\"" + this.TargetUrl(this.maxPage) + "\">" + this.lastText + "</a></li>";
                }

                /**
	             * kiểm tra điều kiện và truyền phần tử vào thẻ chứa paging. 
	             * một số dạng paging sau:
	             * Ký hiệu: X = [none | combobox | editbox]
	             * 1: F P ... 1 2 [X] 4 5 ... N L
	             * 2: ... 1 2 [X] 4 5 ...
	             * 3: 1 2 [X] 4 5
	             * 4: F P N L
	             * 5: [X] N L
	             * 6: N L
	             * 7: P N
	             * 8: ..vv..
	             */

                if (this.ShowFirst && firstLink != null)
                {
                    outputPage.Append(firstLink);
                    outputPage.AppendLine();
                }
                if (this.ShowPrev && prevLink != null)
                {
                    outputPage.Append(prevLink);
                    outputPage.AppendLine();
                }

                if (this.ShowPageNumber && pageLinks.Count > 0)
                {
                    foreach (string link in pageLinks)
                    {
                        outputPage.Append(link);
                        outputPage.AppendLine();
                    }
                }

                if (this.ShowNext && nextLink != null)
                {
                    outputPage.Append(nextLink);
                    outputPage.AppendLine();
                }
                if (this.ShowLast && lastLink != null)
                {
                    outputPage.Append(lastLink);
                    outputPage.AppendLine();
                }
            }

            return outputPage.ToString();
        }

        /// <summary>
        /// Thuộc tính cho trang.
        /// </summary>
        #region Paging Properties
        private string id;
        private string queryString;
        private string param;
        private int perPage;
        private int currentPage;
        private int linksBefore;
        private int linksAfter;
        private string firstText;
        private string prevText;
        private string nextText;
        private string lastText;
        private bool showFirst;
        private bool showPrev;
        private bool showNext;
        private bool showLast;
        private bool showMore;
        private bool showPageNumber;
        private Mode currentMode;
        private string inputInValid;
        private string targetString;
        /// <summary>
        /// ID của thẻ div chứa paging.
        /// </summary>
        public string ID
        {
            get { return id; }
            set { id = value; }
        }
        /// <summary>
        /// Trang liên kết. Chấp nhận 2 dạng sau:
        /// 1: "".
        /// 2: filename.aspx?query.
        /// </summary>
        public string QueryString
        {
            get { return queryString; }
            set { queryString = value; }
        }
        /// <summary>
        /// Biến QueryString.
        /// </summary>
        public string Param
        {
            get { return param; }
            set { param = value; }
        }
        /// <summary>
        /// Số dòng hiển thị trên một trang .
        /// </summary>
        public int PerPage
        {
            get { return perPage; }
            set { perPage = value; }
        }
        /// <summary>
        /// Số của trang hiện tại.
        /// </summary>
        public int CurrentPage
        {
            get { return currentPage; }
            set { currentPage = value; }
        }
        /// <summary>
        /// Số link trước trang hiện tại.
        /// </summary>
        public int LinksBefore
        {
            get { return linksBefore; }
            set { linksBefore = value; }
        }
        /// <summary>
        /// Số link sau trang hiện tai.
        /// </summary>
        public int LinksAfter
        {
            get { return linksAfter; }
            set { linksAfter = value; }
        }
        /// <summary>
        /// Text hiển thị cho link về trang đầu tiên.
        /// </summary>
        public string FirstText
        {
            get { return firstText; }
            set { firstText = value; }
        }
        /// <summary>
        /// Text hiển thị cho link tới trang trước.
        /// </summary>
        public string PrevText
        {
            get { return prevText; }
            set { prevText = value; }
        }
        /// <summary>
        /// Text hiển thị cho link tới trang kế tiếp.
        /// </summary>
        public string NextText
        {
            get { return nextText; }
            set { nextText = value; }
        }
        /// <summary>
        /// Text hiển thị cho link tới trang cuối.
        /// </summary>
        public string LastText
        {
            get { return lastText; }
            set { lastText = value; }
        }
        /// <summary>
        /// Cho phép hiển thị link về trang đầu tiên.
        /// </summary>
        public bool ShowFirst
        {
            get { return showFirst; }
            set { showFirst = value; }
        }
        /// <summary>
        /// Cho phép hiển thị link về trang trước.
        /// </summary>
        public bool ShowPrev
        {
            get { return showPrev; }
            set { showPrev = value; }
        }
        /// <summary>
        /// Cho phép hiển thị link tới trang kế tiếp.
        /// </summary>
        public bool ShowNext
        {
            get { return showNext; }
            set { showNext = value; }
        }
        /// <summary>
        /// Cho phép hiển thị link tới trang cuối.
        /// </summary>
        public bool ShowLast
        {
            get { return showLast; }
            set { showLast = value; }
        }
        /// <summary>
        /// Cho phép hiển thị thông báo tồn tại trang ngoài vùng [...].
        /// </summary>
        public bool ShowMore
        {
            get { return showMore; }
            set { showMore = value; }
        }
        /// <summary>
        /// Cho phép hiển thị link số trang trong vùng.
        /// </summary>
        public bool ShowPageNumber
        {
            get { return showPageNumber; }
            set { showPageNumber = value; }
        }
        /// <summary>
        /// Chế độ tùy chọn cho trang hiện tại.
        /// </summary>
        public Mode CurrentMode
        {
            get { return currentMode; }
            set { currentMode = value; }
        }
        /// <summary>
        /// Chuỗi thông báo khi chọn chế độ Mode.Editbox không hợp lệ.
        /// </summary>
        public string InputInValid
        {
            get { return inputInValid; }
            set { inputInValid = value; }
        }
        /// <summary>
        /// Chuỗi thuộc tính target cho tag A, ví dụ: target="_blank"
        /// </summary>
        public string TargetString
        {
            get { return targetString; }
            set { targetString = value; }
        }
        #endregion
    }


}